package com.atguigu.lease.web.admin.custom.interceptor;

import com.atguigu.lease.common.context.LoginUser;
import com.atguigu.lease.common.context.LoginUserContext;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * Description:
 * 自定义拦截器类，用来拦截所有的前端发送来的请求
 * 拦截后校验JWT token
 * @author Yanxinhao on 2024/11/20
 */
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token信息
        String token = request.getHeader("access_token");
        //2.如果token信息为null，那么说明用户还未登录，那么抛出异常让用户去登录
        if (token == null){
            throw new LeaseException(ResultCodeEnum.ADMIN_LOGIN_AUTH);
        } else {
            //若存在token信息，那么就使用JWT工具类校验token信息是否合法
            Claims claims = JwtUtil.parseToken(token);
            Long userId = claims.get("userId", Long.class);
            String username = claims.get("username", String.class);
            LoginUserContext.setLoginUser(new LoginUser(userId,username));
        }
        return true;
    }
    //拦截器执行完毕之后，清除线程本地常量中的数据
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        /**
         * 这里清空线程本地常量中的数据
         * 因为线程池会复用线程，如果不清空线程本地常量，
         * 那么线程池中的线程就会一直持有登录用户的信息，
         * 导致后续请求无法获取到登录用户信息，甚至获取到错误的登录用户信息
         */
        LoginUserContext.clear();
    }
}